package fun.codedesign.jdk.math.fibonacci;

import java.math.BigDecimal;

public class Factorial {
    /**
     * 阶乘的实现是另一个递归的好例子,数据特别大,用long 或者 <tt>BigDecimal</tt>
     */
    public static void main(String[] args) {
        System.out.println(factorial(20));
        System.out.println(bigFactorial(100));
    }

    /**
     * 时间复杂度O(n)
     *
     * @param n
     * @return long类型
     * @throw ValueOutOfRangeException 超过long范围抛出异常
     */
    public static long factorial(int n) {
        if (n < 1) {
            throw new IllegalArgumentException("n must not be less than 1");
        }
        long value = 1L;
        for (int i = 1; i <= n; i++) {
            // 递归部分
            value *= i;
            //
            if (value < 0) {
                throw new ValueOutOfRangeException("out of the max_value of long");
            }
        }
        return value;
    }

    /**
     * 使用BigDecimal无限大整型和小数点
     * 时间复杂度 O(n) 空间复杂度 O(n)
     *
     * @param n
     * @return
     */
    public static BigDecimal bigFactorial(int n) {
        if (n < 1) {
            throw new IllegalArgumentException("n must not be less than 1");
        }
        BigDecimal value = new BigDecimal(1);
        for (int i = 1; i <= n; i++) {
            // 此处产生了n个新的对象
            value = value.multiply(new BigDecimal(i));
        }
        return value;
    }
}
